iT邦幫忙

1

Web3 DApp 開發 (一):前端與智慧合約的溝通橋樑 (Ethers.js)

  • 分享至 

  • xImage
  •  

一個再安全的智慧合約,如果只能透過命令列(CLI)或 Foundry 腳本來呼叫,對一般使用者來說是毫無意義的。在 Web3 的世界裡,我們需要一個漂亮且直覺的網頁介面來讓使用者與區塊鏈互動,這就是所謂的 DApp (Decentralized Application,去中心化應用程式)。
我將暫時放下 Solidity,回到前端開發者的主場,認識 Web3 前端開發的神兵利器:Ethers.js。

DApp 的底層架構:RPC 與 Ethers.js
在傳統的 Web2 網頁開發中,前端(React / Vue)會透過 HTTP 請求去打後端的 API 伺服器,後端再與資料庫溝通。
但在 Web3 的架構中,智慧合約就是你的後端,區塊鏈就是你的資料庫。

網頁前端要怎麼跟區塊鏈溝通呢?區塊鏈節點有對外開放一種叫做 RPC (Remote Procedure Call) 的介面。然而,手動去打 RPC 請求並處理複雜的資料編碼(ABI encoding)會讓人崩潰。因此,開發社群推出了 Ethers.js 這個 JavaScript 函式庫,它幫我們把所有複雜的底層通訊都包裝成了優雅好用的 JS 函數。

Ethers.js 的三大核心元件
要學好 Ethers.js,你只需要搞懂它世界裡的「三本柱」:

  1. Provider (提供者)
    • 功能:提供區塊鏈的「唯讀 (Read-only)」連線。
    • 能做什麼:你可以透過 Provider 查詢目前的區塊高度、查詢某個地址的餘額、讀取智慧合約裡的公開狀態(例 如 balanceOf),但不能發起會改變區塊鏈狀態的交易。
  2. Signer (簽署者)
    • 功能:代表一個擁有「私鑰」的帳戶。
    • 能做什麼:可以對交易或訊息進行數位簽章。當你要呼叫會改變合約狀態的函數(例如轉帳、鑄造代幣)且需要 支付 Gas 費時,就必須透過 Signer 來發送交易。
  3. Contract (合約抽象物件)
    • 功能:把區塊鏈上的一串二進位 Bytecode,映射成 JavaScript 裡的物件。
    • 能做什麼:只要給它合約地址與 ABI,你就能像呼叫普通 JS 函數一樣去呼叫智慧合約的方法(例如
      contract.transfer())。

什麼是 ABI (Application Binary Interface)?
當我們把 Solidity 編譯並部署上鏈後,它會變成機器才看得懂的 Bytecode。前端的 JavaScript 根本不知道這個合約有哪些函數、需要傳什麼參數。

ABI 就是合約的「說明書」或「菜單」。它是一個 JSON 格式的陣列,詳細記錄了這個合約所有公開函數的名稱、參數型別與回傳值。每次編譯合約時,Foundry 或 Hardhat 都會自動幫你生成這份 ABI。在前端實作時,我們必須把這份 ABI 匯入進來。

實戰:用 Ethers.js 讀取鏈上數據
讓我們來寫一段最簡單的 Node.js/ 前端腳本,示範如何連線到區塊鏈並讀取我們在 Day 11 發行的 ERC20 代幣合約。

首先,安裝 Ethers.js (目前主流為 v6 版本):
'''
npm install ethers
'''
接著,撰寫連接程式碼:
'''
// 引入 ethers
const { ethers } = require("ethers");

// 1. 準備合約的 ABI (只挑選我們需要用到的函數即可)
const tokenABI = [
// 查詢餘額的唯讀函數
"function balanceOf(address owner) view returns (uint256)",
// 查詢代幣名稱的唯讀函數
"function name() view returns (string)"
];

// 2. 設定合約地址與 Provider
const contractAddress = "0xYourTokenContractAddressHere"; // 替換成你部署的合約地址
// 這裡我們使用公開的 RPC 節點 (例如以太坊主網或測試網),實務上常使用 Infura 或 Alchemy
const provider = new ethers.JsonRpcProvider("https://rpc.sepolia.org");

async function main() {
// 3. 建立 Contract 物件 (傳入地址、ABI 與 Provider)
// 注意:因為我們只傳入了 Provider,所以這個合約物件目前是「唯讀」的
const tokenContract = new ethers.Contract(contractAddress, tokenABI, provider);

console.log("正在連線至區塊鏈並讀取合約...");

// 4. 呼叫合約函數
const tokenName = await tokenContract.name();
console.log(`代幣名稱: ${tokenName}`);

// 查詢某個地址的餘額
const targetAddress = "0x1234567890123456789012345678901234567890";
const balance = await tokenContract.balanceOf(targetAddress);

// 注意:區塊鏈回傳的餘額是包含 18 位小數的大整數 (BigInt),需要轉換為人類可讀格式
const formattedBalance = ethers.formatUnits(balance, 18);
console.log(`該地址餘額: ${formattedBalance} 顆代幣`);

}

main();
'''

今天我們成功搭起了前端與區塊鏈溝通的橋樑,並透過 Provider 實現了唯讀狀態的資料抓取。

但是,一個真正的 DApp 不能只有「看」的功能,我們必須讓使用者能夠「操作」它。


圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言